package com.young.common.util;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * AES加密工具类
 * @author wangjiyu@imdada.cn
 * @create 2018/12/20
 */
public class AESUtil {

    public static final String KEY_MODE = "AES";//加密方式AES
    public static final String KEY_ALGORITHM = "AES/CBC/PKCS5Padding";//AES算法
    public static final int KEY_LENGTH = 128;//秘钥长度
    public static final String DEFAULT_IV = "aGdJ2zhNpd2wAoHxl/o6rw==";//默认的初始向量
    public static final String CHARSET = "UTF-8";//编码方式

    /**
     * 生成秘钥
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String generateKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance(KEY_MODE);//AES秘钥生成器
        keyGen.init(KEY_LENGTH);//设置秘钥长度
        SecretKey secretKey = keyGen.generateKey();//生成秘钥
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * 加密
     * @param text 明文
     * @param key 秘钥
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     */
    public static String encript(String text, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        return encript(text, key, DEFAULT_IV);
    }

    /**
     * 解密
     * @param ciphertext 密文
     * @param key 秘钥
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     */
    public static String decript(String ciphertext, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        return decript(ciphertext, key, DEFAULT_IV);
    }

    /**
     * 指定初始向量的加密
     * @param text 明文
     * @param key 密钥
     * @param iv 初始向量
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     */
    public static String encript(String text, String key, String iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        IvParameterSpec zeroIv = new IvParameterSpec(Base64.getDecoder().decode(iv));
        //秘钥
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), KEY_MODE);
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);//加解密对象
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, zeroIv);//加密模式
        byte[] res = cipher.doFinal(text.getBytes(CHARSET));//加密
        return Base64.getEncoder().encodeToString(res);
    }

    /**
     * 指定初始向量的解密
     * @param ciphertext 密文
     * @param key 密钥
     * @param iv 初始向量
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     */
    public static String decript(String ciphertext, String key, String iv) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        IvParameterSpec zeroIv = new IvParameterSpec(Base64.getDecoder().decode(iv));
        //秘钥
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), KEY_MODE);
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);//加解密对象
        cipher.init(Cipher.DECRYPT_MODE, secretKey, zeroIv);//解密模式
        byte[] res = cipher.doFinal(Base64.getDecoder().decode(ciphertext));//解密
        return new String(res, CHARSET);
    }

    public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException {
//        String key = "KfydHv0Svhp9UwEkB7rc+g==";//generateKey();
//        System.out.println("秘钥: " + key);
//        String text = "JD_368033261cc";
//        System.out.println("原文: " + text);
//        String s = encript(text, key);//加密
//        System.out.println("加密后: " + s);
//        String s2 = decript(s, key);//解密
//        System.out.println("解密后: " + s2);
//
//        String s3 = encript(text, key, "aGdJ2zhNpd2wAoHxl/o6rw==");//加密
//        System.out.println("初始向量加密后: " + s3);
//        String s4 = decript(s3, key, "aGdJ2zhNpd2wAoHxl/o6rw==");//解密
//        System.out.println("初始向量解密后: " + s4);

        System.out.println(AESUtil.decript("BYB9sezTn6QOn+dxWtn6YkNpYWhfJE6YPCL0uT8Emi8/KfofF2rLIznWm1AaBza7lQUGO/59DIE/kYAzAikZ0DkNKLHU15iNeacZV8ICFPtQcHgL9CXlKLSzcSkmF8bACf/tRAi6Ql9G2fBTOXGai01UZPy+NaCG1A7LoRiw2f4olnan3u9MFul8yut9wiFce5m06IWXy243Ho0Si7uxZosQee9k3e2+AfVUFNp/1wf7ql8GFg4jtSUQe3NMxX8JPIF79tDT1+WZIRgaRqS4jG4bOjF91P/NdHLVnQAX7lYhXzI/rMAKR/r1xRGdpjSdiuVwebBHOYkDLgYBEEVYVAW6zwmhlKP1p+VnJAQ9oM6FRg0i6u0hy/NN1udcVKw4kLf1MeZy1/JyZgdogIF/fPof0J3J3igxobn4N06hNfNc7RGLOx2bZMgGpKuIw+Dc8QweZt3vMqbVpaqzAkeRVJ1Nma3K5mROWZb/kgbLiKk=", "KfydHv0Svhp9UwEkB7rc+g==", "aGdJ2zhNpd2wAoHxl/o6rw=="));

    }
}
